home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MPW_TOOL / TOOLS / TOOLS_WI / BYACC__ / YYLEX.C < prev   
C/C++ Source or Header  |  1989-11-19  |  20KB  |  1,117 lines

  1. #include <stdio.h>
  2. #include "defs.h"
  3. #include "dep.h"
  4. #include "files.h"
  5. #include "new.h"
  6. #include "symtab.h"
  7. #include "text.h"
  8. #include "tokens.h"
  9.  
  10. #define MAX_BUFFER    4096
  11. #define BUFFER_DELTA    2048
  12.  
  13. extern int lineno;
  14. extern YYSTYPE yylval;
  15.  
  16. LOCAL char *buffer;
  17. LOCAL int buffer_size;
  18. LOCAL int max_buffer;
  19. LOCAL int mark_count;
  20. LOCAL int at_eof;
  21.  
  22. create_buffer()
  23. {
  24.   buffer = NEW2(MAX_BUFFER, char);
  25.   buffer_size = 0;
  26.   max_buffer = MAX_BUFFER;
  27. }
  28.  
  29. clear_buffer()
  30. {
  31.   buffer_size = 0;
  32. }
  33.  
  34. free_buffer()
  35. {
  36.   FREE(buffer);
  37. }
  38.  
  39. savec(c)
  40. int c;
  41. {
  42.   register char *s, *t;
  43.   register char *old_buffer;
  44.   register int i;
  45.  
  46.   if (buffer_size == max_buffer)
  47.     {
  48.       max_buffer += BUFFER_DELTA;
  49.       old_buffer = t = buffer;
  50.       buffer = s = NEW2(max_buffer, char);
  51.       for (i = 0; i < buffer_size; i++)
  52.     *s++ = *t++;
  53.       FREE(old_buffer);
  54.     }
  55.  
  56.   buffer[buffer_size] = c;
  57.   buffer_size++;
  58. }
  59.  
  60. saves(s)
  61. register char *s;
  62. {
  63.   register int c;
  64.  
  65.   while (c = *s++) savec(c);
  66. }
  67.  
  68. initialize_lex()
  69. {
  70.   at_eof = 0;
  71.   lineno = 1;
  72.   mark_count = 0;
  73.   create_buffer();
  74. }
  75.  
  76. skip_white_space()
  77. {
  78.   register int c;
  79.   register FILE *fp;
  80.   register int done;
  81.   register int inside;
  82.   register int start_line;
  83.   static char comment_msg[] = "unterminated comment";
  84.  
  85.   fp = input_file;
  86.   c = getc(fp);
  87.   done = 0;
  88.   while ( ! done)
  89.     {
  90.       switch (c)
  91.     {
  92.     case SP:  case BS:  case HT:  case VT:
  93.     case FF:  case CR:  case DEL:
  94.       c = getc(fp);
  95.       break;
  96.  
  97.     case NEWLINE:
  98.       lineno++;
  99.       c = getc(fp);
  100.       break;
  101.  
  102.     case '/':
  103.       c = getc(fp);
  104.       if (c != '*')
  105.         illegal_character('/');
  106.       start_line = lineno;
  107.       c = getc(fp);
  108.       inside = 1;
  109.       while (inside)
  110.         {
  111.           if (c == '*')
  112.         {
  113.           c = getc(fp);
  114.           if (c == '/')
  115.             inside = 0;
  116.         }
  117.           else if (c == NEWLINE)
  118.         {
  119.           lineno++;
  120.           c = getc(fp);
  121.         }
  122.           else if (c == EOF)
  123.         error(start_line, comment_msg);
  124.           else
  125.         c = getc(fp);
  126.         }
  127.       c = getc(fp);
  128.       break;
  129.  
  130.     default:
  131.       done = 1;
  132.     }
  133.     }
  134.   ungetc(c, fp);
  135. }
  136.  
  137. get_identifier(c)
  138. register int c;
  139. {
  140.   register int inside;
  141.   register FILE *fp;
  142.  
  143.   fp = input_file;
  144.   inside = 1;
  145.   while (inside)
  146.     {
  147.       savec(c);
  148.       c = getc(fp);
  149.       switch (c)
  150.     {
  151.     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  152.     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  153.     case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  154.     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  155.     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  156.     case 'Z':
  157.     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  158.     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  159.     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  160.     case 'p':  case 'q':  case 'r':  case 's':  case 't':
  161.     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  162.     case 'z':
  163.     case '.':  case '_':
  164.     case '0':  case '1':  case '2':  case '3':  case '4':
  165.     case '5':  case '6':  case '7':  case '8':  case '9':
  166.       break;
  167.  
  168.     default:
  169.       inside = 0;
  170.       break;
  171.     }
  172.     }
  173.   yylval.bp = lookup(IDENTIFIER, buffer, buffer_size);
  174.   ungetc(c, fp);
  175. }
  176.  
  177. int
  178. get_string(c)
  179. register int c;
  180. {
  181.   register FILE *fp;
  182.   register int inside;
  183.   register int quote;
  184.   register int start_line;
  185.   register int n;
  186.   register int token;
  187.   static char string_msg[] = "unterminated string";
  188.  
  189.   fp = input_file;
  190.   quote = c;
  191.   c = getc(fp);
  192.   start_line = lineno;
  193.   inside = 1;
  194.   while (inside)
  195.     {
  196.       switch (c)
  197.     {
  198.     case QUOTE:
  199.     case DOUBLE_QUOTE:
  200.       if (c == quote)
  201.         inside = 0;
  202.       else
  203.         {
  204.           savec(c);
  205.           c = getc(fp);
  206.         }
  207.       break;
  208.  
  209.     case EOF:
  210.     case NEWLINE:
  211.       error(start_line, string_msg);
  212.  
  213.     case BACKSLASH:
  214.       c = getc(fp);
  215.       switch (c)
  216.         {
  217.         case EOF:
  218.           error(start_line, string_msg);
  219.  
  220.         case NEWLINE:
  221.           lineno++;
  222.           c = getc(fp);
  223.           break;
  224.  
  225.         case '0':  case '1':  case '2':  case '3':  case '4':
  226.         case '5':  case '6':  case '7':
  227.           n = NUMERIC_VALUE(c);
  228.           c = getc(fp);
  229.           if (IS_OCTAL(c))
  230.         {
  231.           n = 8*n + NUMERIC_VALUE(c);
  232.           c = getc(fp);
  233.           if (IS_OCTAL(c))
  234.             {
  235.               n = 8*n + NUMERIC_VALUE(c);
  236.               c = getc(fp);
  237.             }
  238.         }
  239.           if (c > MAXCHAR) error(lineno, "illegal character in string");
  240.           savec(n);
  241.           break;
  242.  
  243.         case BACKSLASH:
  244.         case QUOTE:
  245.         case DOUBLE_QUOTE:
  246.           savec(c);
  247.           c = getc(fp);
  248.           break;
  249.  
  250.         case 'b':
  251.           savec(BS);
  252.           c = getc(fp);
  253.           break;
  254.  
  255.         case 't':
  256.           savec(HT);
  257.           c = getc(fp);
  258.           break;
  259.  
  260.         case 'n':
  261.           savec(NEWLINE);
  262.           c = getc(fp);
  263.           break;
  264.  
  265.         case 'v':
  266.           savec(VT);
  267.           c = getc(fp);
  268.           break;
  269.  
  270.         case 'f':
  271.           savec(FF);
  272.           c = getc(fp);
  273.           break;
  274.  
  275.         case 'r':
  276.           savec(CR);
  277.           c = getc(fp);
  278.           break;
  279.  
  280.         default:
  281.           error(lineno, "illegal escape sequence");
  282.         }
  283.       break;
  284.  
  285.     default:
  286.       savec(c);
  287.       c = getc(fp);
  288.       break;
  289.     }
  290.     }
  291.  
  292.   if (buffer_size == 1)
  293.     {
  294.       if (buffer[0] == NUL) error(start_line, "null character not allowed");
  295.       yylval.bp = lookup(CHARACTER, buffer, buffer_size);
  296.       token = CHARACTER;
  297.     }
  298.   else
  299.     {
  300.       yylval.bp = lookup(STRING, buffer, buffer_size);
  301.       token = STRING;
  302.     }
  303.   return (token);
  304. }
  305.  
  306. get_number(c)
  307. register int c;
  308. {
  309.   register FILE *fp;
  310.   register int n, k;
  311.   register int inside;
  312.  
  313.   fp = input_file;
  314.   n = NUMERIC_VALUE(c);
  315.   inside = 1;
  316.   while (inside)
  317.     {
  318.       c = getc(fp);
  319.       switch (c)
  320.     {
  321.     case '0':  case '1':  case '2':  case '3':  case '4':
  322.     case '5':  case '6':  case '7':  case '8':  case '9':
  323.       k = NUMERIC_VALUE(c);
  324.       if (n > MAX_TOKEN_NUMBER/10 ||
  325.         (n == MAX_TOKEN_NUMBER/10 && k > MAX_TOKEN_NUMBER%10))
  326.         error(lineno, "number too large");
  327.  
  328.       n = 10*n + k;
  329.       break;
  330.  
  331.     default:
  332.       inside = 0;
  333.       break;
  334.     }
  335.     }
  336.   yylval.i = n;
  337.   ungetc(c, fp);
  338. }
  339.  
  340. save_comment()
  341. {
  342.   register int c;
  343.   register FILE *fp;
  344.   register int inside;
  345.   register int start_line;
  346.   static char comment_msg[] = "unterminated comment";
  347.  
  348.   fp = input_file;
  349.   savec('/');
  350.   savec('*');
  351.   start_line = lineno;
  352.   c = getc(fp);
  353.   inside = 1;
  354.   while (inside)
  355.     {
  356.       switch (c)
  357.     {
  358.     case EOF:
  359.       error(start_line, comment_msg);
  360.  
  361.     case '*':
  362.       savec(c);
  363.       c = getc(fp);
  364.       if (c == '/')
  365.         {
  366.           savec(c);
  367.           inside = 0;
  368.         }
  369.       break;
  370.  
  371.     case NEWLINE:
  372.       lineno++;
  373.       savec(c);
  374.       c = getc(fp);
  375.       break;
  376.  
  377.     default:
  378.       savec(c);
  379.       c = getc(fp);
  380.       break;
  381.     }
  382.     }
  383. }
  384.  
  385. save_string(c)
  386. register int c;
  387. {
  388.   register FILE *fp;
  389.   register int quote;
  390.   register int inside;
  391.   register int start_line;
  392.   static char string_msg[] = "unterminated string";
  393.  
  394.   fp = input_file;
  395.   quote = c;
  396.   savec(quote);
  397.   start_line = lineno;
  398.   c = getc(fp);
  399.   inside = 1;
  400.   while (inside)
  401.     {
  402.       switch (c)
  403.     {
  404.     case EOF:
  405.     case NEWLINE:
  406.       error(start_line, string_msg);
  407.  
  408.     case QUOTE:
  409.     case DOUBLE_QUOTE:
  410.       savec(c);
  411.       if (c == quote)
  412.         inside = 0;
  413.       else
  414.         c = getc(fp);
  415.       break;
  416.  
  417.     case BACKSLASH:
  418.       savec(c);
  419.       c = getc(fp);
  420.       if (c == EOF)
  421.         error(start_line, string_msg);
  422.       else if (c == NEWLINE)
  423.         lineno++;
  424.       savec(c);
  425.       c = getc(fp);
  426.       break;
  427.  
  428.     default:
  429.       savec(c);
  430.       c = getc(fp);
  431.       break;
  432.     }
  433.     }
  434. }
  435.  
  436. save_text()
  437. {
  438.   register int c;
  439.   register FILE *fp;
  440.   register int inside;
  441.   register int start_line;
  442.   static char text_msg[] = "unterminated text";
  443.  
  444.   fp = input_file;
  445.   start_line = lineno;
  446.   c = getc(fp);
  447.   inside = 1;
  448.   while (inside)
  449.     {
  450.       switch (c)
  451.     {
  452.     case EOF:
  453.       error(start_line, text_msg);
  454.       
  455.     case '%':
  456.       c = getc(fp);
  457.       if (c == '}')
  458.         inside = 0;
  459.       else
  460.         savec('%');
  461.       break;
  462.  
  463.     case BACKSLASH:
  464.       c = getc(fp);
  465.       if (c == '}')
  466.         inside = 0;
  467.       else
  468.         savec(BACKSLASH);
  469.       break;
  470.  
  471.     case '/':
  472.       c = getc(fp);
  473.       if (c == '*')
  474.         {
  475.           save_comment();
  476.           c = getc(fp);
  477.         }
  478.       else
  479.         savec('/');
  480.       break;
  481.  
  482.     case QUOTE:
  483.     case DOUBLE_QUOTE:
  484.       save_string(c);
  485.       c = getc(fp);
  486.       break;
  487.  
  488.     case NEWLINE:
  489.       lineno++;
  490.       savec(c);
  491.       c = getc(fp);
  492.       break;
  493.  
  494.     default:
  495.       savec(c);
  496.       c = getc(fp);
  497.       break;
  498.     }
  499.     }
  500. }
  501.  
  502. int
  503. match (s, m, t, n)
  504. register char *s, *t;
  505. int m, n;
  506. {
  507.   register int i;
  508.   register int result;
  509.  
  510.   if (m != n)
  511.     result = 0;
  512.   else
  513.     {
  514.       result = 1;
  515.       for (i = n; i > 0 && result; i--)
  516.     if (*s++ != *t++)
  517.       result = 0;
  518.     }
  519.   return (result);
  520. }
  521.  
  522. save_union_text()
  523. {
  524.   register int c;
  525.   register FILE *fp;
  526.   register int done;
  527.   register int level;
  528.   register int start_line;
  529.   static char union_msg[] = "malformed union declaration";
  530.  
  531.   fp = input_file;
  532.   start_line = lineno;
  533.   saves("typedef union");
  534.   c = getc(fp);
  535.   level = 0;
  536.   done = 0;
  537.   while ( ! done)
  538.     {
  539.       switch (c)
  540.     {
  541.     case EOF:
  542.       error(start_line, union_msg);
  543.  
  544.     case '{':
  545.       level++;
  546.       savec(c);
  547.       c = getc(fp);
  548.       break;
  549.  
  550.     case '}':
  551.       level--;
  552.       savec(c);
  553.       if (level == 0)
  554.         done = 1;
  555.       else
  556.         c = getc(fp);
  557.       break;
  558.  
  559.     case '/':
  560.       c = getc(fp);
  561.       if (c == '*')
  562.         {
  563.           save_comment();
  564.           c = getc(fp);
  565.         }
  566.       else
  567.         savec('/');
  568.       break;
  569.  
  570.     case QUOTE:
  571.     case DOUBLE_QUOTE:
  572.       save_string(c);
  573.       c = getc(fp);
  574.       break;
  575.  
  576.     case NEWLINE:
  577.       lineno++;
  578.       savec(c);
  579.       c = getc(fp);
  580.       break;
  581.  
  582.     default:
  583.       savec(c);
  584.       c = getc(fp);
  585.       break;
  586.     }
  587.     }
  588.   saves(" YYSTYPE;\n");
  589.   yylval.tp = mk_text(start_line, buffer, buffer_size);
  590. }
  591.  
  592. int
  593. special_symbol(c)
  594. register int c;
  595. {
  596.   register FILE *fp;
  597.   register int token;
  598.   register int start_line;
  599.   register int strophe;
  600.   register int inside;
  601.   static char malformed_msg1[] = "malformed %-symbol";
  602.   static char malformed_msg2[] = "malformed \\-symbol";
  603.   static char unknown_msg[] = "unknown keyword";
  604.  
  605.   fp = input_file;
  606.   strophe = c;
  607.   c = getc(fp);
  608.   switch (c)
  609.     {
  610.     case '{':
  611.       start_line = lineno;
  612.       save_text();
  613.       yylval.tp = mk_text(start_line, buffer, buffer_size);
  614.       token = TEXT;
  615.       break;
  616.  
  617.     case '%':
  618.     case BACKSLASH:
  619.       mark_count++;
  620.       if (mark_count < 2)
  621.     token = MARK;
  622.       else
  623.     {
  624.       at_eof = 1;
  625.       token = END_OF_FILE;
  626.     }
  627.       break;
  628.  
  629.     case '<':
  630.       token = LEFT;
  631.       break;
  632.  
  633.     case '>':
  634.       token = RIGHT;
  635.       break;
  636.  
  637.     case '0':
  638.       token = TOKEN;
  639.       break;
  640.  
  641.     case '2':
  642.       token = NONASSOC;
  643.       break;
  644.  
  645.     case '=':
  646.       token = PREC;
  647.       break;
  648.  
  649.     case 'B':  case 'L':  case 'N':  case 'P':  case 'R':
  650.     case 'S':  case 'T':  case 'U':
  651.     case 'b':  case 'l':  case 'n':  case 'p':  case 'r':
  652.     case 's':  case 't':  case 'u':
  653.       inside = 1;
  654.       while (inside)
  655.     {
  656.       savec(c);
  657.       c = getc(fp);
  658.       switch (c)
  659.         {
  660.         case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  661.         case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  662.         case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  663.         case 'p':  case 'q':  case 'r':  case 's':  case 't':
  664.         case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  665.         case 'z':
  666.         case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  667.         case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  668.         case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  669.         case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  670.         case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  671.         case 'Z':
  672.           break;
  673.  
  674.         default:
  675.           inside = 0;
  676.         }
  677.     }
  678.       ungetc(c, fp);
  679.       switch (buffer[0])
  680.     {
  681.     case 'B':
  682.       if (match(buffer, buffer_size, "BINARY", 6))
  683.         token = NONASSOC;
  684.       else
  685.         error(lineno, unknown_msg);
  686.       break;
  687.  
  688.     case 'L':
  689.       if (match(buffer, buffer_size, "LEFT", 4))
  690.         token = LEFT;
  691.       else
  692.         error(lineno, unknown_msg);
  693.       break;
  694.  
  695.     case 'N':
  696.       if (match(buffer, buffer_size, "NONASSOC", 8))
  697.         token = NONASSOC;
  698.       else
  699.         error(lineno, unknown_msg);
  700.       break;
  701.  
  702.     case 'P':
  703.       if (match(buffer, buffer_size, "PREC", 4))
  704.         token = PREC;
  705.       else
  706.         error(lineno, unknown_msg);
  707.       break;
  708.  
  709.     case 'R':
  710.       if (match(buffer, buffer_size, "RIGHT", 5))
  711.         token = RIGHT;
  712.       else
  713.         error(lineno, unknown_msg);
  714.       break;
  715.  
  716.     case 'S':
  717.       if (match(buffer, buffer_size, "START", 5))
  718.         token = START;
  719.       else
  720.         error(lineno, unknown_msg);
  721.       break;
  722.  
  723.     case 'T':
  724.       if (match(buffer, buffer_size, "TERM", 4) ||
  725.           match(buffer, buffer_size, "TOKEN", 5))
  726.         token = TOKEN;
  727.       else if (match(buffer, buffer_size, "TYPE", 4))
  728.         token = TYPE;
  729.       else
  730.         error(lineno, unknown_msg);
  731.       break;
  732.  
  733.     case 'U':
  734.       if (match(buffer, buffer_size, "UNION", 5))
  735.         {
  736.           clear_buffer();
  737.           save_union_text();
  738.           token = UNION_TEXT;
  739.         }
  740.       else
  741.         error(lineno, unknown_msg);
  742.       break;
  743.  
  744.     case 'b':
  745.       if (match(buffer, buffer_size, "binary", 6))
  746.         token = NONASSOC;
  747.       else
  748.         error(lineno, unknown_msg);
  749.       break;
  750.  
  751.     case 'l':
  752.       if (match(buffer, buffer_size, "left", 4))
  753.         token = LEFT;
  754.       else
  755.         error(lineno, unknown_msg);
  756.       break;
  757.  
  758.     case 'n':
  759.       if (match(buffer, buffer_size, "nonassoc", 8))
  760.         token = NONASSOC;
  761.       else
  762.         error(lineno, unknown_msg);
  763.       break;
  764.  
  765.     case 'p':
  766.       if (match(buffer, buffer_size, "prec", 4))
  767.         token = PREC;
  768.       else
  769.         error(lineno, unknown_msg);
  770.       break;
  771.  
  772.     case 'r':
  773.       if (match(buffer, buffer_size, "right", 5))
  774.         token = RIGHT;
  775.       else
  776.         error(lineno, unknown_msg);
  777.       break;
  778.  
  779.     case 's':
  780.       if (match(buffer, buffer_size, "start", 5))
  781.         token = START;
  782.       else
  783.         error(lineno, unknown_msg);
  784.       break;
  785.  
  786.     case 't':
  787.       if (match(buffer, buffer_size, "term", 4) ||
  788.           match(buffer, buffer_size, "token", 5))
  789.         token = TOKEN;
  790.       else if (match(buffer, buffer_size, "type", 4))
  791.         token = TYPE;
  792.       else
  793.         error(lineno, unknown_msg);
  794.       break;
  795.  
  796.     case 'u':
  797.       if (match(buffer, buffer_size, "union", 5))
  798.         {
  799.           clear_buffer();
  800.           save_union_text();
  801.           token = UNION_TEXT;
  802.         }
  803.       else
  804.         error(lineno, unknown_msg);
  805.       break;
  806.     }
  807.       break;
  808.  
  809.     case 'A':  case 'C':  case 'D':  case 'E':  case 'F':
  810.     case 'G':  case 'H':  case 'I':  case 'J':  case 'K':
  811.     case 'M':  case 'O':  case 'Q':  case 'V':  case 'W':
  812.     case 'X':  case 'Y':  case 'Z':
  813.     case 'a':  case 'c':  case 'd':  case 'e':  case 'f':
  814.     case 'g':  case 'h':  case 'i':  case 'j':  case 'k':
  815.     case 'm':  case 'o':  case 'q':  case 'v':  case 'w':
  816.     case 'x':  case 'y': case 'z':
  817.       error(lineno, unknown_msg);
  818.  
  819.     default:
  820.       if (strophe == '%')
  821.     error(lineno, malformed_msg1);
  822.       else
  823.     error(lineno, malformed_msg2);
  824.     }
  825.   return (token);
  826. }
  827.  
  828. get_action()
  829. {
  830.   register int c;
  831.   register FILE *fp;
  832.   register int level;
  833.   register int start_line;
  834.   static char action_msg[] = "unterminated action";
  835.  
  836.   fp = input_file;
  837.   start_line = lineno;
  838.   saves("\t\t\t{");
  839.   c = getc(fp);
  840.   level = 1;
  841.   while (level > 0)
  842.     {
  843.       switch (c)
  844.     {
  845.     case EOF:
  846.       error(start_line, action_msg);
  847.  
  848.     case '{':
  849.       level++;
  850.       savec(c);
  851.       c = getc(fp);
  852.       break;
  853.  
  854.     case '}':
  855.       level--;
  856.       savec(c);
  857.       if (level > 0)
  858.         c = getc(fp);
  859.       break;
  860.  
  861.     case '/':
  862.       c = getc(fp);
  863.       if (c == '*')
  864.         {
  865.           save_comment();
  866.           c = getc(fp);
  867.         }
  868.       else
  869.         savec('/');
  870.       break;
  871.  
  872.     case QUOTE:
  873.     case DOUBLE_QUOTE:
  874.       save_string(c);
  875.       c = getc(fp);
  876.       break;
  877.  
  878.     case NEWLINE:
  879.       lineno++;
  880.       savec(c);
  881.       c = getc(fp);
  882.       break;
  883.  
  884.     default:
  885.       savec(c);
  886.       c = getc(fp);
  887.       break;
  888.     }
  889.     }
  890.   yylval.tp = mk_text(start_line, buffer, buffer_size);
  891. }
  892.  
  893. get_old_fashioned_action()
  894. {
  895.   register int c;
  896.   register FILE *fp;
  897.   register int inside;
  898.   register int start_line;
  899.   static char action_msg[] = "unterminated action";
  900.  
  901.   fp = input_file;
  902.   start_line = lineno;
  903.   skip_white_space();
  904.   c = getc(fp);
  905.   if (c == '{')
  906.     get_action();
  907.   else
  908.     {
  909.       saves("\t\t\t");
  910.       inside = 1;
  911.       while (inside)
  912.     {
  913.       switch (c)
  914.         {
  915.         case EOF:
  916.           error(start_line, action_msg);
  917.  
  918.         case ';':
  919.           savec(c);
  920.           inside = 0;
  921.           break;
  922.  
  923.         case '/':
  924.           c = getc(fp);
  925.           if (c == '*')
  926.         {
  927.           save_comment();
  928.           c = getc(fp);
  929.         }
  930.           else
  931.         savec('/');
  932.           break;
  933.  
  934.         case QUOTE:
  935.         case DOUBLE_QUOTE:
  936.           save_string(c);
  937.           c = getc(fp);
  938.           break;
  939.  
  940.         case NEWLINE:
  941.           lineno++;
  942.           savec(c);
  943.           c = getc(fp);
  944.           break;
  945.  
  946.         default:
  947.           savec(c);
  948.           c = getc(fp);
  949.           break;
  950.         }
  951.     }
  952.       yylval.tp = mk_text(start_line, buffer, buffer_size);
  953.     }
  954. }
  955.  
  956. get_type_identifier()
  957. {
  958.   register int c;
  959.   register FILE *fp;
  960.   register int inside;
  961.   register int start_line;
  962.   static char type_id_msg[] = "malformed type-identifier";
  963.  
  964.   fp = input_file;
  965.   start_line = lineno;
  966.   skip_white_space();
  967.   c = getc(fp);
  968.   switch (c)
  969.     {
  970.     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  971.     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  972.     case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  973.     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  974.     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  975.     case 'Z':
  976.     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  977.     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  978.     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  979.     case 'p':  case 'q':  case 'r':  case 's':  case 't':
  980.     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  981.     case 'z':
  982.     case '_':
  983.       break;
  984.  
  985.     default:
  986.       error(start_line, type_id_msg);
  987.     }
  988.  
  989.   inside = 1;
  990.   while (inside)
  991.     {
  992.       savec(c);
  993.       c = getc(fp);
  994.       switch (c)
  995.     {
  996.     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  997.     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  998.     case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  999.     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  1000.     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  1001.     case 'Z':
  1002.     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  1003.     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  1004.     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  1005.     case 'p':  case 'q':  case 'r':  case 's':  case 't':
  1006.     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  1007.     case 'z':
  1008.     case '_':
  1009.     case '0':  case '1':  case '2':  case '3':  case '4':
  1010.     case '5':  case '6':  case '7':  case '8':  case '9':
  1011.       break;
  1012.  
  1013.     default:
  1014.       inside = 0;
  1015.     }
  1016.     }
  1017.   ungetc(c, fp);
  1018.   skip_white_space();
  1019.   c = getc(fp);
  1020.   if (c != '>') error(start_line, type_id_msg);
  1021.   yylval.bp = lookup(TYPE_IDENTIFIER, buffer, buffer_size);
  1022. }
  1023.  
  1024. int
  1025. yylex()
  1026. {
  1027.   register int c;
  1028.   register FILE *fp;
  1029.   register int token;
  1030.  
  1031.   fp = input_file;
  1032.   clear_buffer();
  1033.   if (at_eof)
  1034.     token = END_OF_FILE;
  1035.   else
  1036.     {
  1037.       clear_buffer();
  1038.       skip_white_space();
  1039.       c = getc(fp);
  1040.       switch (c)
  1041.     {
  1042.     case EOF:
  1043.       at_eof = 1;
  1044.       token = END_OF_FILE;
  1045.       break;
  1046.  
  1047.     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  1048.     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  1049.     case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
  1050.     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  1051.     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  1052.     case 'Z':
  1053.     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  1054.     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  1055.     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  1056.     case 'p':  case 'q':  case 'r':  case 's':  case 't':
  1057.     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  1058.     case 'z':
  1059.     case '.':  case '_':
  1060.       get_identifier(c);
  1061.       token = IDENTIFIER;
  1062.       break;
  1063.  
  1064.     case QUOTE:
  1065.     case DOUBLE_QUOTE:
  1066.       token = get_string(c);
  1067.       break;
  1068.  
  1069.     case '0':  case '1':  case '2':  case '3':  case '4':
  1070.     case '5':  case '6':  case '7':  case '8':  case '9':
  1071.       get_number(c);
  1072.       token = NUMBER;
  1073.       break;
  1074.  
  1075.     case '%':
  1076.     case BACKSLASH:
  1077.       token = special_symbol(c);
  1078.       break;
  1079.  
  1080.     case '{':
  1081.       get_action();
  1082.       token = ACTION;
  1083.       break;
  1084.  
  1085.     case '=':
  1086.       get_old_fashioned_action();
  1087.       token = ACTION;
  1088.       break;
  1089.  
  1090.     case ',':
  1091.       token = COMMA;
  1092.       break;
  1093.  
  1094.     case ':':
  1095.       token = COLON;
  1096.       break;
  1097.  
  1098.     case ';':
  1099.       token = SEMICOLON;
  1100.       break;
  1101.  
  1102.     case '|':
  1103.       token = BAR;
  1104.       break;
  1105.  
  1106.     case '<':
  1107.       get_type_identifier();
  1108.       token = TYPE_IDENTIFIER;
  1109.       break;
  1110.  
  1111.     default:
  1112.       illegal_character(c);
  1113.     }
  1114.     }
  1115.   return (token);
  1116. }
  1117.